package org.jeecg.modules.goods.util;

import lombok.Getter;
import lombok.Setter;
import org.jeecg.common.exception.JeecgBootException;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.core.ResponseInputStream;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.*;

import javax.annotation.PostConstruct;
import java.io.InputStream;

@Component
@ConfigurationProperties(prefix = "aws.s3")
@Getter
@Setter
public class S3Util {

    private String accessKey;
    private String secretKey;
    private String region;
    private String bucketName;

    private S3Client s3Client;

    @PostConstruct
    public void S3Util() {
        // 初始化 S3 客户端
        this.s3Client = S3Client.builder()
                .region(Region.of(region))
                .credentialsProvider(StaticCredentialsProvider.create(
                        AwsBasicCredentials.create(accessKey, secretKey)))
                .build();
    }

    /**
     * 上传文件到 S3
     *
     * @param key      S3 中的文件路径（如：folder/file.txt）
     * @param content  文件内容输入流
     */
    public void uploadFile(String key, InputStream content) {
        try {
            PutObjectRequest putObjectRequest = PutObjectRequest.builder()
                    .bucket(bucketName)
                    .key(key)
                    .build();
            // 注意：InputStream#available 并非总是返回内容总长度，这里建议在业务侧使用字节数组上传
            s3Client.putObject(putObjectRequest, RequestBody.fromInputStream(content, content.available()));
        } catch (Exception e) {
            throw new JeecgBootException("上传文件失败", e);
        }
    }

    /**
     * 以字节数组上传，并设置公开读权限与内容类型（适合图片外网访问）
     *
     * @param key         S3 对象Key
     * @param data        文件字节内容
     * @param contentType 内容类型（如 image/jpeg、image/png）
     */
    public void uploadPublicFile(String key, byte[] data, String contentType) {
        try {
            PutObjectRequest putObjectRequest = PutObjectRequest.builder()
                    .bucket(bucketName)
                    .key(key)
                    .build();
            s3Client.putObject(putObjectRequest, RequestBody.fromBytes(data));
        } catch (Exception e) {
            throw new JeecgBootException("上传公开文件失败", e);
        }
    }

    /**
     * 删除 S3 中的文件
     *
     * @param key S3 中的文件路径（如：folder/file.txt）
     */
    public void deleteFile(String key) {
        try {
            DeleteObjectRequest deleteObjectRequest = DeleteObjectRequest.builder()
                    .bucket(bucketName)
                    .key(key)
                    .build();

            s3Client.deleteObject(deleteObjectRequest);
        } catch (S3Exception e) {
            throw new JeecgBootException("删除文件失败", e);
        }
    }

    /**
     * 获取 S3 文件的预签名 URL
     *
     * @param key S3 中的文件路径
     * @return 文件的访问 URL
     */
    public String getFileUrl(String key) {
        return s3Client.utilities().getUrl(builder -> builder.bucket(bucketName).key(key)).toExternalForm();
    }

    /**
     * 下载 S3 文件内容
     *
     * @param key S3 中的文件路径
     * @return 文件内容的输入流
     */
    public InputStream downloadFile(String key) {
        GetObjectRequest getObjectRequest = GetObjectRequest.builder()
                .bucket(bucketName)
                .key(key)
                .build();
        ResponseInputStream<GetObjectResponse> response = s3Client.getObject(getObjectRequest);
        return response;
    }
}
